# Copyright (C) 2006  Apptility LLC  http://www.apptility.com
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

class AjubySalesforcePipe

    require 'integration/ajuby_soap_box'
    require 'integration/service_result'
    
    ADAPTER_STRING_CONST = "AjubySalesforceAdapter"
    
     def init_config_settings
      @mashup_node = MashupNode.find_by_name('salesforce') 
      @SFORCE_CONFIG = Hash.new()
      @SFORCE_CONFIG['username']=@mashup_node.username
      @SFORCE_CONFIG['password']=AjubyTools.base64decode(@mashup_node.password)
      @SFORCE_CONFIG['debug_soap']=@mashup_node.debug_soap
      @SFORCE_CONFIG['records_size']=@mashup_node.records_size
      @SFORCE_CONFIG['wsdl_url']=@mashup_node.wsdl_url
      #YAML::load(File.open("#{RAILS_ROOT}/app/apis/integration/salesforce/config.yml"))
      #AjubyLogger.logInfo("@SFORCE_CONFIG<<<< : #{@SFORCE_CONFIG}")
     end
            
     def initialize 
       init_config_settings
       @debug = @SFORCE_CONFIG['debug_soap']
       # #{RAILS_ROOT}/app/apis/integration/salesforce/salesforce-enterprise.wsdl
       @login_context = LoginContext.new()
       @login_context.wsdl_url = "#{RAILS_ROOT}/"<< @SFORCE_CONFIG['wsdl_url']
       @login_context.login_user_name = @SFORCE_CONFIG['username']
       @login_context.login_password = @SFORCE_CONFIG['password']
       @records_size = @SFORCE_CONFIG['records_size']
       #AjubyLogger.logInfo("BF:@login_context.wsdl_url: #{@login_context.wsdl_url}")
     end
          
     def login()
       begin
         service = AjubySoapBox.connect(login_context.wsdl_url, debug_soap)
         @login_result = service.login(get_login_options)
         set_post_login_data(@login_result)
         # Create header handler for consecutive calls
         @header_handler_obj = PostLoginHeader.get_header(login_context.session_id)
         #AjubyLogger.logInfo("service: #{service} | debug_soap: #{debug_soap} | session_id: #{login_context.session_id}| \n server_url: #{login_context.server_url} | user_id: #{login_context.user_id}")
         return AjubySoapBox::ServiceResult.new(AjubySoapBox::Codes::CONNECTED_SUCCESSFULLY, @login_result , "Connected successfuly to Salesforce")
       rescue Exception => e
          AjubyLogger.logInfo("##################Saleforce Adapter failed to connect: #{e.message}")
          return AjubySoapBox::ServiceResult.new(AjubySoapBox::Codes::COULD_NOT_CONNECT,nil, e.message)
       end          
    end
  
   
    def get_modules_list
      begin
        service = connect
        @global_resp_object = service.describeGlobal({})
        @modules_list = @global_resp_object.result.types
        @modules_list
      rescue Exception => e
        raise AjubySalesforcePipe.build_err_trace("#{ADAPTER_STRING_CONST}: get_modules_list call failed : " << e.message)
      end
          
    end  

    def get_module_records(size, module_name)
      # options would be the array of fields querying, if options null get *
      # module_name = Contact , Account etc
      # size = number of records restored, if not specified default it from yml file
      begin
        service = connect
        if size == nil
            size = records_size
        end
        options = Array.new()
        options.push("name")
        @query_str = build_query_str_from_options(options, module_name)    
        @global_resp_object = service.query({"queryString"=>@query_str})
        @modules_list = @global_resp_object.result.records
        @record_names = Array.new()
        @modules_list.each {|record|
          @record_names.push(record['Name'])
          }    
        @record_names
      rescue Exception => e
        raise AjubySalesforcePipe.build_err_trace("#{ADAPTER_STRING_CONST}: get_module_records call failed : " << e.message)
      end
      
    end  

  
    def build_query_str_from_options(options, queried_obj_name)
      @query_str =""
      if options==nil
        @query_str = "*"
      else
        options.each {|option_element|
         @query_str = @query_str + "#{option_element}," 
        }
        @query_str = @query_str[0,@query_str.length-1]
      end
      @query_str = "select #{@query_str} from #{queried_obj_name}"
      @query_str  
    end  
    
    def get_login_options
      @service_call_options = Hash.new()
      @service_call_options['username'] = login_context.login_user_name
      @service_call_options['password'] = login_context.login_password
      @service_call_options
    end
      
    def set_post_login_data login_result
      login_context.session_id = login_result.result.sessionId
      login_context.server_url = login_result.result.serverUrl
      #login_user_name.password_expired = login_result.result.passwordExpired
      login_context.user_id = login_result.result.userId
    end

    def self.is_connection_failed(service_result)
      connection_failed = false
      if service_result !=nil
        if(service_result.code == AjubySoapBox::Codes::COULD_NOT_CONNECT)
          connection_failed = true
        else
          connection_failed = false
        end  
      end
      connection_failed
    end
   
    def connect
      #AjubyLogger.logInfo("header_handler_obj>> #{header_handler_obj} | session_id >> #{session_id}")
      @service_result = nil
      if (header_handler_obj == nil and login_context.session_id == nil)
        @service_result = login
      end
      
      if AjubySalesforcePipe.is_connection_failed(@service_result)
        raise AjubySalesforcePipe.build_err_trace("[ Connection failed " <<@service_result.connection_message << " ]")
      else
        post_login_connect
      end
        
    end
    
    def self.build_err_trace(err_msg)
      err_msg = "<br>&nbsp;-->"<<err_msg
      err_msg
    end
        
    def post_login_connect()
      AjubySoapBox.connect_w_header(login_context.wsdl_url, login_context.server_url, debug_soap, header_handler_obj)
    end
      
    def debug_soap
      if debug=='true'
         return 'true'
      else
         return 'false'
      end
    end
  
    def records_size
     @records_size
    end   

  
    def header_handler_obj
      @header_handler_obj
    end
      
    def debug
     @debug
    end   
   
    def login_context
      @login_context
    end  
    

  class LoginContext
    
    def initialize
        
    end
      
    def wsdl_url
      @wsdl_url
    end   

    def wsdl_url=(wsdl_url)
      @wsdl_url = wsdl_url
    end   
   
    def session_id
      @session_id
    end   

    def session_id=(session_id)
      @session_id = session_id
    end   

    def server_url
     @server_url
    end   

    def server_url=(server_url)
      @server_url = server_url
    end   
  
    def user_id
     @user_id
    end 

    def user_id=(user_id)
      @user_id = user_id
    end   

    def login_user_name
     @login_user_name
    end 

    def login_user_name=(login_user_name)
      @login_user_name = login_user_name
    end   

    def login_password
     @login_password
    end 

    def login_password=(login_password)
      @login_password = login_password
    end 
    
    def name
     @name
    end 

    def name=(name)
      @name = name
    end    
    
  end
      
  class PostLoginHeader 
    @@HEADER_NAME = "SessionHeader"
    @@HEADER_NAMESPACE = "urn:enterprise.soap.sforce.com"
    
    def self.get_header(login_session_id)
      options = {"sessionId"=>[login_session_id, @@HEADER_NAMESPACE]}
      header_handler = AjubySoapBox::SOAPHeaderHandler.new(@@HEADER_NAME, @@HEADER_NAMESPACE, options)
      header_handler
    end  
    
  end   
  
end